package com.example.administrator.demorecyclerview.auto_viewpager;

import android.content.Context;
import android.support.annotation.Nullable;
import android.support.v4.util.SparseArrayCompat;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;

/**
 * Created by Administrator on 2018/1/9.
 */

public class HeaderFooterRecyclerView extends EmptyRecyclerView {
    private HeaderAdapter mAdapter;


    public HeaderFooterRecyclerView(Context context) {
        super(context);
//        setAdapter(null);
    }

    public HeaderFooterRecyclerView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
//        setAdapter(null);
    }

    public HeaderFooterRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
//        setAdapter(null);
    }


    //    @Override
//    public void setAdapter(Adapter adapter) {
//        if (adapter != null) {
//            super.setAdapter(new HeaderAdapter(adapter, null, null));
//        } else {
//            super.setAdapter(adapter);
//        }
//    }
//    public void setHeaderAdapter(View headerView, Adapter adapter) {
//        if (headerView == null) {
//            throw new NullPointerException("headView is Null!");
//        }
//        setAdapter(new HeaderAdapter(adapter, headerView, null));
//    }
//
//    public void setFooterAdapter(View footerView, Adapter adapter) {
//        if (footerView == null) {
//            throw new NullPointerException("footerView is Null!");
//        }
//        setAdapter(new HeaderAdapter(adapter, null, footerView));
//    }


    @Override
    public void setAdapter(RecyclerView.Adapter adapter) {
        final HeaderAdapter old = mAdapter;
        makeAdapterAndRegisterObserver(adapter, old);
        super.setAdapter(mAdapter);
    }

    @Override
    public Adapter getAdapter() {
        return mAdapter == null ? null : mAdapter.mInternalAdapter;
    }

    final private RecyclerView.AdapterDataObserver mCheckObserver = new RecyclerView.AdapterDataObserver() {
        @Override
        public void onChanged() {
            checkIsEmpty();
        }

        @Override
        public void onItemRangeInserted(int positionStart, int itemCount) {
            checkIsEmpty();
        }

        @Override
        public void onItemRangeRemoved(int positionStart, int itemCount) {
            checkIsEmpty();
        }
    };

//    public void setHeaderFooterAdapter(View[] headerView, View[] footerView, Adapter adapter) {
//        if (headerView == null) {
//            throw new NullPointerException("headView is Null!");
//        }
//        if (footerView == null) {
//            throw new NullPointerException("footerView is Null!");
//        }
//
//
//        setAdapter(new HeaderAdapter(adapter, headerView, footerView));
//    }

//    public void addHeaderView(View headerView) {
//        addHeaderView(m);
//    }

    public void addHeaderView(int index, View headerView) {
        if (mAdapter == null) {
//            mAdapter = new HeaderAdapter(null);
            makeAdapterAndRegisterObserver(null, null);
        }
        mAdapter.addHeaderView(index, headerView);
    }

//    public void addHeaderView(View headerView) {
//        addHeaderView(getHeaderCount(), headerView);
//    }

    public boolean removeHeaderView(int index) {
        if (mAdapter != null) {
            return mAdapter.removeHeaderView(index);
        }
        return false;
    }

    public boolean removeHeaderView(View headerView) {
        if (mAdapter != null) {
            return mAdapter.removeHeaderView(headerView);
        }
        return false;
    }

    public void addFooterView(int index, View footerView) {
        if (mAdapter == null) {
//            mAdapter = new HeaderAdapter(null);
            makeAdapterAndRegisterObserver(null, null);
        }
        mAdapter.addFooterView(index, footerView);
    }

    public boolean removeFooterView(int index) {
        if (mAdapter != null) {
            return mAdapter.removeFooterView(index);
        }
        return false;
    }

    public boolean removeFooterView(View footerView) {
        if (mAdapter != null) {
            return mAdapter.removeFooterView(footerView);
        }
        return false;
    }

    private void makeAdapterAndRegisterObserver(final RecyclerView.Adapter internalAdapter, final HeaderAdapter oldHeaderAdapter) {
        if (oldHeaderAdapter != null) {
            oldHeaderAdapter.unregisterAdapterDataObserver(mCheckObserver);
            mAdapter = new HeaderAdapter(internalAdapter, oldHeaderAdapter);
        } else {
            mAdapter = new HeaderAdapter(internalAdapter);
        }
        mAdapter.registerAdapterDataObserver(mCheckObserver);
    }


    public HeaderAdapter getHeaderAdapter() {
        return mAdapter;
    }

//    public int getRealIndex(int index) {
//        return index - mAdapter.getHeaderCount();
//    }

    public int getHeaderCount() {
        return mAdapter == null ? 0 : mAdapter.getHeaderCount();
    }

    public int getFooterCount() {
        return mAdapter == null ? 0 : mAdapter.getFooterCount();
    }

    private static final class HeaderAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
        private RecyclerView.Adapter mInternalAdapter;
        //        private ArrayList<View> headerView;
//        private ArrayList<View> footerView;
        private final SparseArray<View> mHeader;
        private final SparseArray<View> mFooter;
        private InternalAdapterDataObserver mInternalAdapterDataObserver;
        private static final int DEFAULT_MAX_EXTRA_COUNT = 2;

        public void addHeaderView(int index, View view) {
            if (index < 0)
                throw new IllegalArgumentException("headerView index should>=0");
            final int keyInArray = getHeaderKey(index);
            int indexInArray = mHeader.indexOfKey(keyInArray);
            if (indexInArray > -1) {
                throw new IllegalStateException("add headerView index(" + index + ")has already existed");
//                mHeader.setValueAt(indexInArray, view);
//                int indexInAdapter = mHeader.size() - indexInArray - 1;
//                notifyItemChanged(indexInAdapter);
//                Log.i("@@@", "@@@@@@@:" + indexInAdapter);
            } else {
                mHeader.append(keyInArray, view);
                indexInArray = mHeader.indexOfKey(keyInArray);
                int indexInAdapter = mHeader.size() - indexInArray - 1;
                notifyItemInserted(indexInAdapter);
            }

//            notifyDataSetChanged();
        }

        public boolean removeHeaderView(int index) {
            final int keyInArray = getHeaderKey(index);
            int indexInArray = mHeader.indexOfKey(keyInArray);
            if (indexInArray > -1) {
                int indexInAdapter = mHeader.size() - indexInArray - 1;
                mHeader.removeAt(indexInArray);
                notifyItemRemoved(indexInAdapter);
                return true;
            }
            return false;
        }

        public boolean removeHeaderView(View view) {
            int indexInArray = mHeader.indexOfValue(view);
            if (indexInArray > -1) {
                int indexInAdapter = mHeader.size() - indexInArray - 1;
                mHeader.removeAt(indexInArray);
                notifyItemRemoved(indexInAdapter);
                return true;
            }
            return false;
        }

        private int getHeaderKey(int index) {
            return -index - 1;
        }

        private int getFooterKey(int index) {
//            final int footerUpHeaderCount = getHeaderCount() + getInternalAdapterItemCount();
//            final int contentDownFooterX = index - footerUpHeaderCount;
            return Integer.MIN_VALUE + index;
        }


        public void addFooterView(int index, View view) {
            if (index < 0)
                throw new IllegalArgumentException("footerView index should>=0");
            final int keyInArray = getFooterKey(index);
            int indexInArray = mFooter.indexOfKey(keyInArray);
            if (indexInArray > -1) {
                throw new IllegalStateException("add footerView index(" + index + ")has already existed");


            } else {
                mFooter.append(keyInArray, view);
                indexInArray = mFooter.indexOfKey(keyInArray);
                int indexInAdapter = getHeaderCount() + getInternalAdapterItemCount() + indexInArray;
                notifyItemInserted(indexInAdapter);
            }
        }

        public boolean removeFooterView(int index) {
            final int keyInArray = getFooterKey(index);
            int indexInArray = mFooter.indexOfKey(keyInArray);
            if (indexInArray > -1) {
                int indexInAdapter = getHeaderCount() + getInternalAdapterItemCount() + indexInArray;
                mFooter.removeAt(indexInArray);
                notifyItemRemoved(indexInAdapter);
                return true;
            }
            return false;
        }

        public boolean removeFooterView(View view) {
            int indexInArray = mFooter.indexOfValue(view);
            if (indexInArray > -1) {
                int indexInAdapter = getHeaderCount() + getInternalAdapterItemCount() + indexInArray;
                mFooter.removeAt(indexInArray);
                notifyItemRemoved(indexInAdapter);
                return true;
            }
            return false;
        }


        HeaderAdapter(RecyclerView.Adapter adapter, HeaderAdapter copyFrom) {
            mInternalAdapter = adapter;
            mHeader = copyFrom.mHeader;
            mFooter = copyFrom.mFooter;
        }


        private HeaderAdapter(RecyclerView.Adapter adapter) {
            mInternalAdapter = adapter;
            mHeader = new SparseArray<>(DEFAULT_MAX_EXTRA_COUNT);
            mFooter = new SparseArray<>(DEFAULT_MAX_EXTRA_COUNT);
        }

        @Override
        public int getItemViewType(int position) {
//            final int headerCount = getHeaderCount();
//            int x = position - headerCount;
//            if(position>=headerCount)
//            {
//                return mAdapter.getItemViewType(position);
//            }


            int contentUpHeaderX = position - getHeaderCount();

            if (contentUpHeaderX < 0) {
//                mHeader.put(-position - 1, position);
//                Log.i("@@","getItemViewType,position:"+position+",type:"+contentUpHeaderX);

                return -position - 1;
            }


            final int footerUpHeaderCount = getHeaderCount() + getInternalAdapterItemCount();
            final int contentDownFooterX = position - footerUpHeaderCount;
            if (contentDownFooterX >= 0) {
                int footerUpHeaderX = Integer.MIN_VALUE + contentDownFooterX;
//                mFooter.put(footerUpHeaderX, position);
//                Log.i("@@","getItemViewType,position:"+position+",type:"+footerUpHeaderX);

                return footerUpHeaderX;
            }

            final int adapterType = mInternalAdapter.getItemViewType(position);
            if (adapterType < 0)
                throw new IllegalStateException("adapter viewType should >=0");
//            Log.i("@@","getItemViewType,position:"+position+",type:"+adapterType);

            return adapterType;
        }

        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//            Log.i("@@", "onCreateViewHolder,type:" + viewType);

            if (viewType < 0) {
                View view;
                if ((view = mHeader.get(viewType)) != null) {
                    view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
                    return new RecyclerView.ViewHolder(view) {
                        @Override
                        public String toString() {
                            return super.toString();
                        }
                    };
                }
                if ((view = mFooter.get(viewType)) != null) {
                    view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
                    return new RecyclerView.ViewHolder(view) {
                        @Override
                        public String toString() {
                            return super.toString();
                        }
                    };
                }
                return null;
            } else {
                return mInternalAdapter.onCreateViewHolder(parent, viewType);
            }


//            if (viewType == ITEM_TYPE_HEADER) {
//                headerView.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
//                return new ViewHolder(headerView) {
//                    @Override
//                    public String toString() {
//                        return super.toString();
//                    }
//                };
//            } else {
//                return mAdapter.onCreateViewHolder(parent, viewType);
//            }
//            if (viewType >= 0) {
//                return mAdapter.onCreateViewHolder(parent, viewType);
//            }
//            if (headerView != null) {
//                headerView.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
//                return new ViewHolder(headerView) {
//                    @Override
//                    public String toString() {
//                        return super.toString();
//                    }
//                };
//            }

        }

        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
//            Log.i("@@", "onBindViewHolder,position:" + position);

            int numHeaders = getHeaderCount();
            final int adjPosition = position - numHeaders;
            final int adapterCount = getInternalAdapterItemCount();
            if (position >= numHeaders && adjPosition < adapterCount) {
                mInternalAdapter.onBindViewHolder(holder, adjPosition);
            }

        }


        class InternalAdapterDataObserver extends RecyclerView.AdapterDataObserver {
            @Override
            public void onChanged() {
                notifyDataSetChanged();
//                notifyItemRangeChanged(getHeaderCount(), getInternalAdapterItemCount());
            }

            @Override
            public void onItemRangeChanged(int positionStart, int itemCount) {
                notifyItemRangeChanged(positionStart + getHeaderCount(), itemCount);
            }

            @Override
            public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
                notifyItemRangeChanged(positionStart + getHeaderCount(), itemCount, payload);
            }

            @Override
            public void onItemRangeInserted(int positionStart, int itemCount) {
                notifyItemRangeInserted(positionStart + getHeaderCount(), itemCount);
            }

            @Override
            public void onItemRangeRemoved(int positionStart, int itemCount) {
                notifyItemRangeRemoved(positionStart + getHeaderCount(), itemCount);
            }

            @Override
            public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
                final int headerCount = getHeaderCount();
                notifyItemMoved(fromPosition + headerCount, toPosition + headerCount);
            }
        }

        @Override
        public void registerAdapterDataObserver(RecyclerView.AdapterDataObserver observer) {
            super.registerAdapterDataObserver(observer);


            if (mInternalAdapter != null) {
                if (mInternalAdapterDataObserver == null) {
                    mInternalAdapterDataObserver = new InternalAdapterDataObserver();
                    mInternalAdapter.registerAdapterDataObserver(mInternalAdapterDataObserver);
                }
            }
        }

        @Override
        public void unregisterAdapterDataObserver(RecyclerView.AdapterDataObserver observer) {
            super.unregisterAdapterDataObserver(observer);
            if (mInternalAdapter != null && mInternalAdapterDataObserver != null) {
                mInternalAdapter.unregisterAdapterDataObserver(mInternalAdapterDataObserver);
                mInternalAdapterDataObserver = null;
            }
        }


        final int getHeaderCount() {
            return mHeader.size();
        }

        final int getFooterCount() {
            return mFooter.size();
        }

        @Override
        public int getItemCount() {
            return getHeaderCount() + getInternalAdapterItemCount() + getFooterCount();
        }

        public int getInternalAdapterItemCount() {
            return mInternalAdapter == null ? 0 : mInternalAdapter.getItemCount();
        }

    }

    @Override
    boolean checkIsEmpty() {
//        final Adapter adapter = getAdapter();
        if (mAdapter != null && mAdapter.getInternalAdapterItemCount() > 0) {
            hideEmptyView();
            return false;
        } else {
            showEmptyView();
            return true;
        }
    }

    @Override
    boolean checkIsError() {
//        final Adapter adapter = getAdapter();
        if (mAdapter != null && mAdapter.getInternalAdapterItemCount() > 0) {
            hideEmptyView();
            return false;
        } else {
            showEmptyView();
            return true;
        }
    }


}
